/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Description: implement of oem_auth_result_storage
 * Author: Kit Framework group
 * Create: 2021-04-26
 */

#include "oem_auth_result_storage.h"

#include <stdio.h>
#include "securec.h"

#include "duet_flash_kv.h"

#define MAX_FILE_BYTES_LIMIT 5120U

#define RESET_FILE_CONTENT_LEN 3U
#define RESET_FILE_MAGIC_CONTENT "ABC"
#define RESET_FILE_NAME "auth_reset"

#define TICKET_FILE_NAME "auth_ticket"
#define AUTH_STATS_FILE_NAME "auth_stats"

bool OEMIsOverTemperatureLimit(void)
{
    /*
     * if device has temprature limit while write data,
     * read the temperature through the manufacturer's interface,
     * and return true when the temperature exceeds the limit.
     */
    return false;
}

static int32_t GetKVPairDataLen(const char *key)
{
    if (key == NULL) {
        printf("OEM Adapter: Invalid parameter for %s\n", __FUNCTION__);
        return -1;
    }

    // no length 1 byte auth result
    char fakeBuf[1];
    int32_t len = sizeof(fakeBuf);
    (void)duet_flash_kv_get(key, fakeBuf, &len);
    printf("OEM Adapter : DEBUG : key[%s], len[%d]\n", key, len);
    if (len == 1) {
        return -1;
    }
    return len;
}

static int32_t GetKVPairData(const char *key, char *buffer, uint32_t bufferLen)
{
    if (key == NULL || buffer == NULL || bufferLen == 0) {
        printf("OEM Adapter: Invalid parameter for %s\n", __FUNCTION__);
        return -1;
    }
    int32_t dataLen = GetKVPairDataLen(key);
    if (dataLen == -1) {
        printf("OEM Adapter: Empty data for %s\n", key);
        return -1;
    }
    if (dataLen > bufferLen) {
        printf("OEM Adapter: Invalid buffer length for read %s\n", key);
        return -1;
    }
    if (duet_flash_kv_get(key, buffer, &bufferLen) < 0) {
        printf("OEM Adapter: Read %s data failed\n", key);
        return -1;
    }
    return 0;
}

static int32_t SetKVPairData(const char *key, const char *data, uint32_t dataLen)
{
    if (key == NULL || data == NULL || dataLen > MAX_FILE_BYTES_LIMIT) {
        printf("OEM Adapter: Invalid parameter for %s\n", __FUNCTION__);
        return -1;
    }
    if (duet_flash_kv_set(key, data, dataLen, 1) < 0) {
        printf("OEM Adapter: Set [%s] data failed\n", key);
        return -1;
    }
    return 0;
}

static bool IsKVPairExist(const char *key)
{
    if (key == NULL) {
        printf("OEM Adapter: Invalid parameter for %s\n", __FUNCTION__);
        return false;
    }
    if (GetKVPairDataLen(key) == -1) {
        return false;
    }
    return true;
}

static int32_t DeleteKVPair(const char *key)
{
    if (key == NULL) {
        printf("OEM Adapter: Invalid parameter for %s\n", __FUNCTION__);
        return -1;
    }
    if (duet_flash_kv_del(key) != 0) {
        printf("OEM Adapter: Delete [%s] failed\n", key);
        return -1;
    }
    return 0;
}

bool OEMIsResetFlagExist(void)
{
    return IsKVPairExist(RESET_FILE_NAME);
}

int32_t OEMCreateResetFlag(void)
{
    return SetKVPairData(RESET_FILE_NAME, RESET_FILE_MAGIC_CONTENT, RESET_FILE_CONTENT_LEN);
}

int32_t OEMDeleteResetFlag(void)
{
    return DeleteKVPair(RESET_FILE_NAME);
}

bool OEMIsAuthStatusExist(void)
{
    return IsKVPairExist(AUTH_STATS_FILE_NAME);
}

int32_t OEMWriteAuthStatus(const char *data, uint32_t len)
{
    if (data == NULL || len == 0) {
        return -1;
    }
    return SetKVPairData(AUTH_STATS_FILE_NAME, data, len);
}

int32_t OEMReadAuthStatus(char *buffer, uint32_t bufferLen)
{
    if (buffer == NULL || bufferLen == 0) {
        return -1;
    }
    return GetKVPairData(AUTH_STATS_FILE_NAME, buffer, bufferLen);
}

int32_t OEMDeleteAuthStatus(void)
{
    return DeleteKVPair(AUTH_STATS_FILE_NAME);
}

int32_t OEMGetAuthStatusFileSize(uint32_t *len)
{
    if (len == NULL) {
        return -1;
    }
    *len = GetKVPairDataLen(AUTH_STATS_FILE_NAME);
    if (*len == -1) {
        return -1;
    }
    return 0;
}

bool OEMIsTicketExist(void)
{
    return IsKVPairExist(TICKET_FILE_NAME);
}

int32_t OEMWriteTicket(const char *data, uint32_t len)
{
    if (data == NULL || len == 0) {
        return -1;
    }
    return SetKVPairData(TICKET_FILE_NAME, data, len);
}

int32_t OEMReadTicket(char *buffer, uint32_t bufferLen)
{
    if (buffer == NULL || bufferLen == 0) {
        return -1;
    }
    return GetKVPairData(TICKET_FILE_NAME, buffer, bufferLen);
}

int32_t OEMDeleteTicket(void)
{
    return DeleteKVPair(TICKET_FILE_NAME);
}

int32_t OEMGetTicketFileSize(uint32_t *len)
{
    if (len == NULL) {
        return -1;
    }
    *len = GetKVPairDataLen(TICKET_FILE_NAME);
    if (*len == -1) {
        return -1;
    }
    return 0;
}
